#include <iostream>

class Animal
{
public:
    int age{5};
    void bark()
    {
        std::cout << "Animal Barking !" << std::endl;
    }

    Animal(const Animal &animal)
    {
        std::cout << "Animal 拷贝构造函数执行了" << std::endl;
    }

    Animal()
    {
    }
};

class Dog : public Animal
{
public:
    void bark()
    {
        std::cout << "Dog Barking!!" << std::endl;
    }

    Dog(int age)
    {
        this->age = age;
        std::cout << "Dog(age) 构造方法执行了" << std::endl;
    }

    Dog(const Dog &dog)
    {
        std::cout << "Dog 拷贝构造函数执行了 " << std::endl;
    }
};

int main(int argc, char const *argv[])
{
    
    Dog dog{1};
    dog.bark();

    // 父类的引用指向子类对象
    Animal animal = dog; // 会调用animal 的拷贝构造函数
    animal.bark();

    Animal &animalPreference = dog; // 不会调用animal 的拷贝构造函数s
    animalPreference.bark();

    // 父类的指针指向子类对象
    Dog *bulutuo = new Dog(10);
    bulutuo->bark();
    Animal *animalBulutuo = bulutuo;
    animalBulutuo->bark();
    /*
    因为在没有使用虚函数的情况下，指针或引用的静态类型决定了调用哪个版本的函数。在这里，animalBulutuo 是一个 Animal* 类型的指针，即使它实际上指向了 Dog 对象，但由于静态类型是 Animal*，所以调用 bark 函数时会使用基类 Animal 的版本。
    */
    std::cout << animalBulutuo->age << std::endl;

    std::cout << "*************" << std::endl;

    std::cout << &dog << std::endl;
    std::cout << &animal << std::endl;
    std::cout << &animalPreference << std::endl;
    std::cout << bulutuo << std::endl;
    std::cout << animalBulutuo << std::endl;

    return 0;
}
